DHCP协议

通过同DHCP服务器的交互,设备可以获得一个有效的IP地址,使得它可以在特定网络环境下运行。DHCP服务器一般有两个数据库,一个数据库维护静态分配的物理地址和IP地址地址绑定,它记录了特定客户端主机将被分配的特定IP地址,客户主机可以永久使用这些IP地址;第二个数据库维护了一个IP地址池,其中记录了可以动态分配的IP地址,当客户端主机请求临时主机分配时,如果客户段的物理地址在静态数据库中有对应的IP地址项,则服务器将该IP地址将被分配给客户段,如果没有对应项,则服务器在地址池中为客户段分配一个地址。

DHCP协议有着自身的报文组织形式,并且使用UDP进行报文的传输。LwIP中实现了DHCP客户端的功能,当该客户端启动时,它会自动向DHCP服务器(默认网关,192.168.1.1)发送地址分配请求,若得到正确的响应,它会将有效地址设置到网络接口结构的相关字段中。

测试程序

要使用LwIP提供的DHCP功能,首先需要设置用户配置文件lwipopts.h,打开与DHCP功能相关的宏开关:

1
2
#define LWIP_DHCP 1
#define MEMP_NUM_SYS_TIMEOUT 6

LWIP_DHCP为1表示允许系统的DHCP功能,同时与DHCP功能相关的dns.c将会被编译;MEMP_NUM_SYS_TIMEOUT指明了编译器将为内核结构sys_timeo分配的内存池个数,默认值为3,DHCP模块需要使用两个定时器结构来实现定时操作,在无操作系统模拟层环境下运行时,用户需要周期性的调用DHCP的两个定时函数dhcp_coarse_tmr和dhcp_fine_tmr,它们的典型周期是60s和500ms。

使用了DHCP,用户就不必手动为网络接口分配IP地址了,因此需要对lwip_init_task进行修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// lwipdemo.c
#include "dhcp.h" // DHCP相关的头文件
#include "includes.h" // 操作系统相关的头文件
struct netif rt18019_netif;
void lwip_init_task(void) {
struct ip_addr ipaddr, netmask, gw;
tcpip_init(NULL, NULL); // 初始化协议栈
IP4_ADDR(&gw, 0, 0, 0, 0);
IP4_ADDR(&ipaddr, 0, 0, 0, 0);
IP4_ADDR(&netmask, 0, 0, 0, 0);
// 初始化网络接口,注册回调函数
netif_add(&rt18019_netif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, tcpip_input);
netif_set_default(&rt18019_netif);
netif_set_up(&re18019_netif);
dhcp_start(&rt18019_netif); / 启动DHCP客户端
}

函数dhcp_start将为系统启动一个DHCP客户端,该客户端基于UDP实现,函数会在内核中为客户端申请一个UDP控制块,并将控制块和DHCP服务器(默认网关,192.168.1.1)进行绑定。